package com.foreverwin.mes.lims.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.foreverwin.mes.common.constants.HandleBOConstants;
import com.foreverwin.mes.common.enums.HandleEnum;
import com.foreverwin.mes.core.base.FrontPage;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.foreverwin.mes.core.exception.BusinessException;
import com.foreverwin.mes.core.utils.StringUtils;
import com.foreverwin.mes.lims.enums.InspectObject;
import com.foreverwin.mes.lims.enums.InspectType;
import com.foreverwin.mes.lims.mapper.InspectPlanDetailMapper;
import com.foreverwin.mes.lims.model.InspectPlan;
import com.foreverwin.mes.lims.mapper.InspectPlanMapper;
import com.foreverwin.mes.lims.model.InspectPlanDetail;
import com.foreverwin.mes.lims.model.InspectProject;
import com.foreverwin.mes.lims.model.InspectTask;
import com.foreverwin.mes.lims.service.InspectPlanDetailService;
import com.foreverwin.mes.lims.service.InspectPlanService;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.foreverwin.mes.lims.service.InspectProjectService;
import com.foreverwin.mes.lims.service.InspectTaskService;
import com.foreverwin.mes.lims.util.DataValueConstant;
import com.foreverwin.mes.meapi.model.*;
import com.foreverwin.mes.meapi.service.*;
import org.springframework.stereotype.Service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.util.*;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author Levy
 * @since 2020-02-20
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class InspectPlanServiceImpl extends ServiceImpl<InspectPlanMapper, InspectPlan> implements InspectPlanService {


    @Autowired
    private InspectPlanMapper inspectPlanMapper;
    @Autowired
    private WorkCenterService workCenterService;
    @Autowired
    private OperationService operationService;
    @Autowired
    private ItemGroupService itemGroupService;
    @Autowired
    private ResrceService resrceService;
    @Autowired
    private InspectPlanDetailService inspectPlanDetailService;
    @Autowired
    private InspectTaskService inspectTaskService;
    @Autowired
    private InspectProjectService inspectProjectService;
    @Autowired
    private CertificationService certificationService;
    @Autowired
    CustomFieldsService customFieldsService;

    @Override
    public Page<InspectPlan> selectPage(FrontPage<InspectPlan> frontPage, InspectPlan inspectPlan) {
        EntityWrapper<InspectPlan> queryWrapper = new EntityWrapper<>();
        queryWrapper.setEntity(inspectPlan);
        return super.selectPage(frontPage.getPagePlus(), queryWrapper);
    }

    @Override
    public List<InspectPlan> selectList(InspectPlan inspectPlan) {
        EntityWrapper<InspectPlan> queryWrapper = new EntityWrapper<>();
        queryWrapper.setEntity(inspectPlan);
        return super.selectList(queryWrapper);
    }

    @Override
    public void doSave(InspectPlan inspectPlan, JSONArray planArray) {
         //前台数据校验
        inspectPlan = checkInspectPlan( inspectPlan );
        //前台json数组转化为list集合
        List<InspectPlanDetail> formsInspectPlanDetailList = JSONObject.parseArray(planArray.toJSONString(), InspectPlanDetail.class);
        //原有的检验计划项目
        List<InspectPlanDetail> oldInspectPlanList = new ArrayList<>();
        for ( InspectPlanDetail insp :formsInspectPlanDetailList) {
             if ( insp.getHandle() != null ) {
                 oldInspectPlanList.add(insp);
             }
        }
        Date now = new Date();
        String planBo = inspectPlan.getHandle();
        String object = inspectPlan.getObject();
        InspectPlan oldModel = inspectPlanMapper.selectById( planBo );
        String message = "";
        boolean flag = true;
        if ( oldModel !=null ){
            //如果计划被使用,不可以更改
           /* List<InspectTask> inspectTasks =  inspectTaskService.selectList(
                    new EntityWrapper<InspectTask>()
                            .eq( "PLAN_BO" , planBo  )
                            .orderAsc( Arrays.asList( "CREATED_DATE_TIME" ) )
            );
            if ( !inspectTasks.isEmpty() ){
                InspectTask inspectTask = inspectTasks.get( 0 );
                if ( !DataValueConstant.TASK_STATUS_COMPLETE.equals( inspectTask.getTaskStatus() ) ){
                    flag = false;
                }
            }

            if ( !flag ){

                if ( InspectObject.RES.name().equals( object ) ){
                    message = "设备["+HandleEnum.RESOURCE.getPart( oldModel.getResrce() ,1 )+"]";
                }else if ( InspectObject.PRO.name().equals(object ) ){
                    message = "物料组["+oldModel.getItemGroup().split(",")[1]+"]";
                }else if ( InspectObject.ENV.name().equals( object ) ){
                    message = "工作中心["+oldModel.getWorkCenter().split(",")[1]+"]";
                }
                throw BusinessException.build(  message + "对应的检验计划已经存在未完成的任务，该计划不可修改" );
            }*/
           //2020/4/9 Max
            List<InspectPlanDetail>  inspectPlanDetailList = inspectPlanDetailService.selectList(new EntityWrapper<InspectPlanDetail>()
                    .eq("PLAN_BO",planBo));
            for ( InspectPlanDetail ipe:inspectPlanDetailList) {
                //判断是否前台表单数据是否发生变化
                boolean _flag = false;
                if ( oldInspectPlanList.contains(ipe) ) {
                    _flag = true;
                }
                //变化的项查看其是否有未完成的任务
                if ( !_flag ) {
                    List<InspectTask> inspectTasks = inspectTaskService.selectList(new EntityWrapper<InspectTask>()
                            .eq("PLAN_BO", planBo)
                            .eq("INSPECT_TYPE", ipe.getInspectType())
                            .orderAsc(Arrays.asList("CREATED_DATE_TIME")));
                    InspectTask inspectTask = null;
                    if (!inspectTasks.isEmpty()) {
                        inspectTask = inspectTasks.get(0);
                        if (!DataValueConstant.TASK_STATUS_COMPLETE.equals(inspectTask.getTaskStatus())) {
                            flag = false;
                        }
                    }

                    if ( !flag ){

                        if ( InspectObject.RES.name().equals( object ) ){
                            message = "设备["+HandleEnum.RESOURCE.getPart( oldModel.getResrce() ,1 )+"]";
                        }else if ( InspectObject.PRO.name().equals(object ) ){
                            message = "物料组["+oldModel.getItemGroup().split(",")[1]+"]";
                        }else if ( InspectObject.ENV.name().equals( object ) ){
                            message = "工作中心["+oldModel.getWorkCenter().split(",")[1]+"]";
                        }
                        String inspectType = "";
                        if ( inspectTask != null ) {
                            inspectType = inspectTask.getInspectType();
                        }
                        throw BusinessException.build(  message + "的检验计划的检验类型["+inspectType+"]已经存在未完成的任务，该计划不可修改" );
                    }

                }
            }
            //更新数据
            oldModel.setUpdatedDateTime( now );
            oldModel.setUpdatedUser( inspectPlan.getCreatedUser() );
            inspectPlanMapper.updateAllColumnById( oldModel );
        }else {
            //新增
            inspectPlan.setCreatedDateTime( now );
            inspectPlanMapper.insert( inspectPlan );
        }

        doSaveInspectPlanDatail(  planArray  , inspectPlan ,inspectPlan.getSite() );

    }

    public static List<Map<String, Object>> compareTwoClass(Object class1, Object class2) throws ClassNotFoundException, IllegalAccessException {
        List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
        //获取对象的class
        Class<?> clazz1 = class1.getClass();
        Class<?> clazz2 = class2.getClass();
        //获取对象的属性列表
        Field[] field1 = clazz1.getDeclaredFields();
        Field[] field2 = clazz2.getDeclaredFields();
        //遍历属性列表field1
        for (int i = 0; i < field1.length; i++) {
            //遍历属性列表field2
            for (int j = 0; j < field2.length; j++) {
                //如果field1[i]属性名与field2[j]属性名内容相同
                if (field1[i].getName().equals(field2[j].getName())) {
                    field1[i].setAccessible(true);
                    field2[j].setAccessible(true);
                    //如果field1[i]属性值与field2[j]属性值内容不相同
                    if (!compareTwo(field1[i].get(class1), field2[j].get(class2))) {
                        Map<String, Object> map2 = new HashMap<String, Object>();
                        map2.put("name", field1[i].getName());
                        map2.put("old", field1[i].get(class1));
                        map2.put("new", field2[j].get(class2));
                        list.add(map2);
                    }
                    break;
                }
            }
        }
        return list;
    }

    public static boolean compareTwo(Object object1, Object object2) {

        if (object1 == null && object2 == null) {
            return true;
        }
        if (object1 == "" && object2 == null) {
            return true;
        }
        if (object1 == null && object2 == "") {
            return true;
         }
        if (object1 == null && object2 != null) {
            return false;
        }
        if (object1.equals(object2)) {
            return true;
        }
        return false;
    }

    /**
     * 保存计划明细
     * @param planArray
     * @param inspectPlan
     */
    private void  doSaveInspectPlanDatail( JSONArray planArray ,InspectPlan inspectPlan ,String site){
        String planBo = inspectPlan.getHandle();
        Map paramMap = new HashMap();
        paramMap.put("PLAN_BO",planBo);
        inspectPlanDetailService.deleteByMap( paramMap );

        String inspectType;
        String category;
        String time;
        String unit;
        String batchInterval;
        Boolean isSample;
        String sampleStandard;
        String inspectProject;
        String inspectCertificate;
        String revision;
        for (int i=0; i<planArray.size(); i++){
            JSONObject jsonObject =planArray.getJSONObject(i);
            inspectType = jsonObject.getString( "inspectType" );
            category = jsonObject.getString( "category" );
            time = jsonObject.getString( "time" );
            unit = jsonObject.getString( "unit" );
            batchInterval = jsonObject.getString( "batchInterval" );
            isSample = jsonObject.getBoolean( "isSample" );
            sampleStandard = jsonObject.getString( "sampleStandard" );
            inspectProject = jsonObject.getString( "inspectProject" );
            revision = jsonObject.getString( "revision" );
            inspectCertificate = jsonObject.getString( "inspectCertificate" );

            InspectPlanDetail inspectPlanDetail = new InspectPlanDetail();
            if ( "TIME".equals( category ) ){
                if ( StringUtils.isBlank(time)||StringUtils.isBlank(unit) ){
                    throw BusinessException.build("请填写检验类型["+ InspectType.valueOf(inspectType).getDescription() +"]时间!");
                }
                inspectPlanDetail.setTime( time );
                inspectPlanDetail.setUnit( unit );

            }else if ( "SFC".equals( category ) ){
                if ( StringUtils.isBlank( batchInterval ) ){
                    throw BusinessException.build("请填写检验类型["+ InspectType.valueOf(inspectType).getDescription() +"]间隔批次!");
                }
                inspectPlanDetail.setBatchInterval( batchInterval );
            }else {
                throw BusinessException.build("请选择检验类型["+ InspectType.valueOf(inspectType).getDescription() +"]分类!");
            }

            inspectPlanDetail.setHandle( UUID.randomUUID().toString() );
            inspectPlanDetail.setInspectType( inspectType );
            inspectPlanDetail.setCategory( category );
            inspectPlanDetail.setPlanBo( planBo );
            //检验项目必选
            if ( StringUtils.isBlank( inspectProject ) ){
                throw BusinessException.build("请选择检验项目!");
            }
            InspectProject projectModel = inspectProjectService.selectOne( new EntityWrapper<InspectProject>()
                        .eq(InspectProject.PROJECT_NO, inspectProject)
                        .eq(InspectProject.REVISION , revision)
                        .eq(InspectProject.STATUS ,"Y")
            );
               if ( projectModel == null ){
                   throw BusinessException.build("检验项目【"+ inspectProject + "】不存在");
               }
            inspectPlanDetail.setInspectProject( inspectProject );
            inspectPlanDetail.setRevision( revision );
            if ( !StringUtils.isBlank( inspectCertificate ) ){

                Certification certification = certificationService.selectOne( new EntityWrapper<Certification>()
                        .eq(Certification.CERTIFICATION, inspectCertificate)
                        .eq(Certification.SITE, site) );
                if ( certification == null ){
                    throw BusinessException.build("检验证明【"+ inspectCertificate + "】不存在");
                }
                inspectPlanDetail.setInspectCertificate( inspectCertificate );
            }

            if ( isSample == null ){
                isSample = false;
            }
            if ( isSample ){
                inspectPlanDetail.setIsSample( "true" );
                if ( StringUtils.isBlank( sampleStandard ) ){
                    throw BusinessException.build("请填写取样数量！");
                }

                inspectPlanDetail.setSampleStandard( sampleStandard );
            }

            //外教类型需要修改设备自定义字段（CALIBRATION_CYCLE）外教周期
            if ( InspectType.OS.getCode().equals( inspectType ) ){
               String resrceBo = inspectPlan.getResrce();
               Resrce resrce = resrceService.selectById( resrceBo );
               if ( resrce == null ){
                   throw BusinessException.build("外教类型计划所需设备【"+ HandleEnum.RESOURCE.getPart( resrceBo , 1 ) +"】不存在!");
               }
               CustomFields customFields = new CustomFields();
               customFields.setHandle( resrceBo );
               customFields.setAttribute( DataValueConstant.RES_CALIBRATION_CYCLE );
               customFields.setValue( time + "/" + unit );
               customFields.setCreatedDateTime( new Date() );
               customFields.setModifiedDateTime( new Date() );
               CustomFields oModel = customFieldsService.getAttributeValue( resrceBo , DataValueConstant.RES_CALIBRATION_CYCLE );
               if ( oModel != null ){
                 customFieldsService.delete(
                   new EntityWrapper<CustomFields>()
                   .eq( "HANDLE" , resrceBo )
                   .eq( "ATTRIBUTE" , DataValueConstant.RES_CALIBRATION_CYCLE )
                 );
               }
               customFieldsService.insert( customFields );
            }

            inspectPlanDetailService.insert( inspectPlanDetail );
        }
    }

    /**
     * 环境校验工作中心
     * 产品检验物料组、操作
     * 设备校验设备
     */
    private InspectPlan checkInspectPlan(InspectPlan inspectPlan){
        String planBo ;
        String object = inspectPlan.getObject();
        if (InspectObject.ENV.name().equals( object )){
            if ( StringUtils.isBlank( inspectPlan.getWorkCenter() ) ){
                throw BusinessException.build("请选择工作中心");
            }
            String workCenterBo = inspectPlan.getWorkCenter();
            WorkCenter workCenter = workCenterService.selectById( workCenterBo );
            if ( workCenter == null ){
                throw BusinessException.build("工作中心["+ inspectPlan.getWorkCenter() +"]不存在");
            }
            planBo =HandleBOConstants.INSPECT_PLAN_BO + ":"+ workCenterBo;

            inspectPlan.setItemGroup("");
            inspectPlan.setOperation("");
            inspectPlan.setResrce("");
        }else if ( InspectObject.PRO.name().equals( object ) ){
            if ( StringUtils.isBlank( inspectPlan.getOperation() ) ){
                throw BusinessException.build("请选择工序!");
            }
            if ( StringUtils.isBlank( inspectPlan.getItemGroup() ) ){
                throw BusinessException.build("请选择物料组!");
            }
            //校验操作、物料组是否存在
            String operationBo = inspectPlan.getOperation();
            Operation operation = operationService.selectById( operationBo);
            String itemGroupBo = inspectPlan.getItemGroup();
            ItemGroup itemGroup = itemGroupService.selectById( itemGroupBo );
            if ( operation == null ){
                throw BusinessException.build("操作【"+ operationBo.split(",")[1] +"】不存在");
            }
            if ( itemGroup == null ){
                throw BusinessException.build("物料组【"+ itemGroupBo.split(",")[1] +"】不存在");
            }
            planBo = HandleBOConstants.INSPECT_PLAN_BO + ":" + itemGroupBo;

            inspectPlan.setResrce("");
            inspectPlan.setWorkCenter("");
        }else if ( InspectObject.RES.name().equals( object )){

            if ( StringUtils.isBlank( inspectPlan.getResrce() )){
                throw BusinessException.build("请选择设备!");
            }
            String resrceBo = inspectPlan.getResrce();
            Resrce resrce = resrceService.selectById( resrceBo );
            if ( resrce == null ){
                throw BusinessException.build("设备[" + HandleEnum.RESOURCE.getPart( resrceBo ,1 ) + "]不存在");
            }

            planBo = HandleBOConstants.INSPECT_PLAN_BO + ":" + resrceBo;

            inspectPlan.setWorkCenter("");
            inspectPlan.setItemGroup("");
            inspectPlan.setOperation("");
        }else {
            throw BusinessException.build("请选择正确对象!");
        }
        inspectPlan.setHandle( planBo );



        return inspectPlan;
    }
}